﻿#pragma once
/**
@author 何炜
@date 2011/4/28
@brief .
@details
*/
#include "GLLSingleton.h"
#include "GLLSystem.h"

namespace GLL
{
	class GameState;
	class GameApp;

	class OSApp : public System, public Singleton<OSApp>
	{
	public:
		/**应用开始.
		捕获所有异常，包括系统异常和程序异常.
		@param pGameApp 应用程序自己管理此指针，OSApp不做删除操作
		@remark 此函数中调用Start_CatchSoftException，并且捕获Start_CatchSoftException的
		系统硬异常，进行处理。Start_CatchSoftException 则调用DoStart，并捕获
		DoStart中抛出的软异常(throw std::exception)。DoStart为真正的游戏
		入口。*/
		void Start_CatchAllException(GameApp* pGameApp, GameState& startState);

		/**应用开始.
		只捕获程序抛出的软异常，系统异常需要调用者自己捕获.
		@see Start_CatchAllException*/
		void Start_CatchSoftException(GameApp* pGameApp, GameState& startState);

		/**应用开始.
		没有捕获任何异常，需要调用者自己捕获.
		@see Start_CatchAllException*/
		void Start(GameApp* pGameApp, GameState& startState);

		/**窗口的关闭按钮被按下.
		具体OS系统类型调用此函数*/
		void Shutdown();

		/**.*/
		void ProcOSMessage_spec();

		/**子类定义：窗口创建时的尺寸.*/
		Size2Di GetWindowInitialSize();

		/**子类定义：每帧窗口标题更新.*/
		virtual void GetOSAppTitle(StringStream& out);

		/**.*/
		void SetOSAppTitle_spec(StringStream& in);

		/**创建系统窗口
		@param create_console 是否创建console输出窗
		@return 是否创建成功*/
		void CreateOSWindow_spec();

		/**.*/
		Size2Di GetClientSize_spec();

		/**.*/
		Size2Di GetOSWindowPos_spec();

		/**.*/
		void SetClientSize(const Size2Di& s);

		/**显示系统窗口.*/
		void ShowOSWindow_spec();

		/**销毁系统窗口.*/
		void DestroyOSWindow_spec();

		/**.*/
		void LoadBkPicture_spec();

		/**.*/
		void DrawOSAppBkPicture_spec();

		/**.*/
		void UnloadBkPicture_spec();

		/**.*/
		Size2Di GetScreenSize_spec();

		/**.*/
		Size2Di GetFrameSizeFromClientSize_spec(const Size2Di&);

		/**.*/
		Size2Di GetClientSizeFromFrameSize(const Size2Di&);

		/**.*/
		void MoveOSWindow(const Size2Di& client_size);

		enum ThreadPriority
		{
			TP_NORMAL,
			TP_LOW,
			TP_HIGHT,
			TP_LOWEST,
			TP_HIGHEST,
		};

		/**设置此函数调用线程的优先级.*/
		void SetThisThreadPriority(ThreadPriority tp);

		OSApp();

		GameApp* _game;
	private:

		/**.*/
		void MoveOSWindow_spec(const Area2Di&);

		/**.*/
		void DoSetClientSize_spec(const Size2Di&);

		/**子类定义：窗口的大小改变了
		@param 渲染区域的大小*/
		void OnClientSizeChanged_spec(const Size2Di&);

		/**.*/
		void UpdateWindowTitle();

		/**主循环.*/
		void Loop();

		/**.*/
		void Reset();

		//系统相关：
		//通过宏，可以简化设计，不必使用多态。
		//让你体验到，如果世界上只有一种操作系统，开发是多么简单的事情。
#ifdef GLL_WIN
	private:
		HINSTANCE _hInstance;
		HWND _hWnd;
		HWND _TRACE;
		HANDLE _Console;
		HBITMAP _startBkgnd;
		HINSTANCE RegisterOSWindowClass();

	public:
		virtual const char* _GetClassName(){return "GLL.Win.Cls";}
		HWND GetHWND(){return _hWnd;}

#endif GLL_WIN

	};

};//GLL
